<?php
/**
 * Copyright 2013 Marek Kaszewski
 *
 * This file is part of the JHUB1 Online Community Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Jhub1_Common\Model\Key;

/**
 * The class belongs to JHUB1 PROJECT
 * The class implements methods for like ISBN-10 check digit calculation validation
 * extended to 32 weight value
 * Marek Kaszewski
 * This is used for validation of the developer and agent unique ID
 * The class generates also random address for virtual devices
 * Deployed in HubsController.php
 */

class Generator
{

    private static $keyGeneratorCharacters = 'xyzcd3ea2bh5iju9vwf4gk6mnp7qrs8t';
    private static $UUIDGeneratorCharacters = 'ABCDEFGHIJKLMNOPQRSTUWVPQXYZ1234567890';
    private static $emailActivationGeneratorCharacters = 'ABCDEFGHIJKLMNOPQRSTUWVPQXYZqazwsxedcrfvtgbyhnujmikolp1234567890';
    //  private $weights = array();
    private static $randomKeyLength = 10;
    private static $groupKeyLength = 8;
    private static $agentKeyLength = 10;
    private static $emailActivationKeyLength = 70;
    private static $UUIDKeyLength = array(5, 5, 9);
    private static $UUIDKeySectionDelimiter = '-';

    private function __construct()
    {

    }

    private static function genKey($length = null, $chars)
    {
        if ($length == null) {
            $length = Generator::$randomKeyLength;
        }
        $key = '';
        $harLength = strlen($chars) - 1;
        $sum = 0;
        for ($i = 0; $i < $length; $i++) {
            $randomChar = $chars[rand(0, $harLength)];
            $key .= $randomChar;
            $sum = $sum + ord($randomChar);
        }
        return $key;
    }

    private static function getSum($sum)
    {
        $sumStr = (string)$sum;
        $rawSum = 0;
        for ($i = 0; $i < strlen($sumStr); $i++) {
            $rawSum = $rawSum + ord($sumStr[$i]);
        }
        $sum = Generator::addDigits($rawSum);
        return $sum;
    }

    private static function addDigits($sum)
    {
        $ssum = (string)$sum;
        if (strlen($ssum) > 1) {
            $rawSum = 0;
            for ($i = 0; $i < strlen($ssum); $i++) {
                $rawSum = $rawSum + $ssum[$i];
            }
        }
        if ($rawSum > 9) {
            $rawSum = Generator::addDigits($rawSum);
        }
        return $rawSum;
    }

    public static function genAgentKey()
    {
        return Generator::genKey(Generator::$agentKeyLength, Generator::$keyGeneratorCharacters);
    }

    public static function genGroupKey()
    {
        return Generator::genKey(Generator::$groupKeyLength, Generator::$keyGeneratorCharacters);
    }

    public static function genEmailActivationKey()
    {
        return Generator::genKey(Generator::$emailActivationKeyLength, Generator::$emailActivationGeneratorCharacters);
    }

    // 23 char long sdsddt-dgdfhg-hgkkjkhut   1-5-5-9.3
    public static function genGeneralUUID($objectIDPrefix)
    {
        $UUID = $objectIDPrefix . '-';
        foreach (Generator::$UUIDKeyLength as $length) {
            $UUID = $UUID . Generator::genKey($length, Generator::$UUIDGeneratorCharacters);
            $UUID = $UUID . Generator::$UUIDKeySectionDelimiter;
        }
        $tempUUID = substr($UUID, 0, -(strlen(Generator::$UUIDKeySectionDelimiter)));
        $sum = Generator::calculateSumForUUID($tempUUID);
        return $tempUUID . '.' . $sum;
    }

    public static function calculateSumForUUID($uuid)
    {
        $UUIDparts = explode('.', $uuid);
        $UUIDelements = explode('-', $UUIDparts[0]);
        array_shift($UUIDelements);
        $sum = '';
        foreach ($UUIDelements as $elem) {
            $sum = $sum . Generator::getSum($elem);
        }
        return $sum;
    }

    /**
     * A-NEMC7-QUDXJ-URXEYOIG9.sd4
     * @param $uuid
     * @return bool
     */
    public static function isGeneralUUIDValid($uuid)
    {
        $UUIDparts = explode('.', $uuid);
        // A-NEMC7-QUDXJ-URXEYOIG9
        $sum = Generator::calculateSumForUUID($UUIDparts[0]);
        $newTempUUID = $UUIDparts[0] . '.' . $sum;
        if ($uuid == $newTempUUID) {
            return true;
        }
        return false;
    }

    public static function getUUIDClass($uuid)
    {
        $UUIDparts = explode('-', $uuid);
        if(count($UUIDparts) > 0) {
            return $UUIDparts[0];
        }
        return false;
    }

    /**
     * method genAddress
     * @param int $length prepared key length
     * @param string $hubName user defined hub's name
     * @return string prepared hub's address
     */
    /*    public function genAddress($length = null, $hubName = null)
        {
            return $this->genKey($length) . "_" . $this->stringPrepare($hubName);
        }*/

    /**
     * method stringPrepare
     * @param string $str string for preparation
     * @return string prepared string
     * @todo Implement validation/preparation for string which needs to be compliant with the naming convention
     */
    /*    public function stringPrepare($str)
        {
            return $str;
        }*/

    /**
     * method validateDevKey
     * @param string $devKey developer key generated by dispensing server
     * @return bool depending if the key is validated or not
     * @todo Implement validation/preparation for string which needs to be compliant with the naming convention
     */
    /*    public function validateDevKey($devKey)
        {
            return $this->checkCSum($this->clearString($devKey));
        }

        public function validateAgentKey($agentKey)
        {
            return $this->checkCSum($this->clearString($agentKey));
        }

        private function checkCSum($cleanStr)
        {
            $strLength = strlen($cleanStr);
            if (($strLength == 4) || ($strLength == 6)) {
                return $this->check($strLength, $cleanStr);
            } else {
                return false;
            }
        }

        private function check($length, $str)
        {
            $sum = 0;
            for ($i = 0; $i < $length; $i++) {
                $sum += ($this->weights[$str[$i]] + 1) * ($length - ($i));
            }
            if ($sum % 32 == 0) {
                return true;
            } else {
                return false;
            }
        }

        private function clearString($str)
        {
            $strLength = strlen($str);
            $this->preparePattern();
            $pattern = $this->weights;
            $retStr = "";
            for ($i = 0; $i < $strLength; $i++) {
                if (array_key_exists($str[$i], $pattern)) {
                    $retStr .= $str[$i];
                }
            }
            return $retStr;
        }

        private function preparePattern()
        {
            $length = strlen($this->keyGeneratorCharacters);
            $retArr = array();
            for ($i = 0; $i < $length; $i++) {
                $this->weights[$this->keyGeneratorCharacters[$i]] = $i;
            }
            return $retArr;
        }*/
}

?>
